<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <p>{{name}}</p>
    <p>{{message}}</p>
  </div>
  <script>
    // 正则表达式
    let rkuohao = /\{\{(.+?)\}\}/g;
    function compiler(template, data) {
      let childNode = template.childNodes; // 获取子元素
      for(let i =0;i<childNode.length; i++) {
        // 判断是文本还是元素，文本可能有{{}}
        let type = childNode[i].nodeType; // 1.元素，3.文本
        
        if(type ===3) {
          // 文本节点，判断有没有{{}}
          let txt = childNode[i].nodeValue; // 该属性只有文本节点才有意义，文本节点值
          // 判断文本有没有{{}},用正则表达式rkuohao匹配txt文本，匹配到之后会执行function回调，回调的参数，第一个为匹配到的正则，第二个为替换的值
          txt = txt.replace(rkuohao, function(_, g) {
            // replace使用正则匹配一次就会被调用一次，函数参数0，表示匹配到的内容，第n个参数表示第n组
            let key = g.trim(); // {{}}里边的值，为key，在这里是name和message
            let value = data[key];
            // 将{{}}用value值替换
            return value;
          })
          
          // 注意txt现在和dom元素是没有关系的
          childNode[i].nodeValue = txt;

        } else if(type === 1) {
          // 元素，有没有子元素，判断子元素有没有{{}}，递归
          compiler(childNode[i], data)
        }

      }
    }
    // 构造函数
   function JGVue(options) {
    // 内部数据_开头可读可写，$开头只读
    this._data = options.data;
    this._el = options.el;
    // 准备工作（准备模板）
    this._templateDom = document.querySelector(this._el);
    this._parent = this._templateDom.parentNode;
    // 渲染工作
    this.render()
   }
// 将模板结合数据，得到HTML
   JGVue.prototype.render = function() {
    this.compiler()
   }
   // 编译，模板结合数据
   JGVue.prototype.compiler = function() {
    let realHTMLDOM = this._templateDom.cloneNode(true)
    compiler(realHTMLDOM, this._data)
    this.update(realHTMLDOM)
   }
   // 更新dom，替换到页面中
   JGVue.prototype.update = function(real) {
    this._parent.replaceChild(real, document.querySelector('#root'))
   }

   let app = new JGVue({
     el: '#root',
     data: {
       name: 'zs',
       message: 'message'
     }
   })
  </script>
</body>
</html>